package com.example.java17demo;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64; // 客户端使用了Hex编码，这里也需要对应，或者使用更安全的比较

public class SignatureVerifier {

    // !! 重要 !! 这个密钥必须与Electron端使用的密钥完全一致，并且需要安全地存储和加载
    private static final String SECRET_KEY = "1675fd49deffbeabd610b2944cc6f04c"; // <-- 替换为您的实际密钥

    /**
     * 验证HMAC-SHA256签名
     *
     * @param username          从请求体或其他方式获取的用户名
     * @param machineCode       从请求头 X-Mid 获取的机器码
     * @param timestamp         从请求头 X-Mtimestamp 获取的时间戳 (格式与客户端一致)
     * @param receivedSignature 从请求头 X-Msign 获取的客户端签名 (Hex编码)
     * @return 签名是否有效
     */
    public static boolean verifySignature(String username, String machineCode, String timestamp, String receivedSignature) {
        try {
            // 1. 准备数据字符串 (与客户端生成签名时的数据完全一致)
            String data = username + machineCode + timestamp;

            // 2. 获取HMAC-SHA256实例
            Mac hmacSha256 = Mac.getInstance("HmacSHA256");

            // 3. 准备密钥
            SecretKeySpec secretKeySpec = new SecretKeySpec(SECRET_KEY.getBytes(StandardCharsets.UTF_8), "HmacSHA256");

            // 4. 初始化HMAC实例
            hmacSha256.init(secretKeySpec);

            // 5. 计算签名
            byte[] calculatedSignatureBytes = hmacSha256.doFinal(data.getBytes(StandardCharsets.UTF_8));

            // 6. 将计算出的字节数组转换为Hex字符串，以便与客户端发送的Hex字符串比较
            // (客户端使用了digest('hex'))
            StringBuilder hexString = new StringBuilder();
            for (byte b : calculatedSignatureBytes) {
                String hex = Integer.toHexString(0xff & b);
                if (hex.length() == 1) {
                    hexString.append('0');
                }
                hexString.append(hex);
            }
            String calculatedSignatureHex = hexString.toString();

            // 7. 比较计算出的签名与收到的签名
            // 使用安全的比较方法，防止时序攻击 ( embora timingSafeEqual 在字节数组上工作更好)
            // 简单字符串比较在长度不同时是安全的，但长度相同时可能存在微小时序差异。
            // 更安全的做法是先将收到的Hex字符串解码为字节数组再比较，但解析Hex有额外开销。
            // 对于一般应用，直接比较Hex字符串通常足够。
            boolean signatureMatch = calculatedSignatureHex.equalsIgnoreCase(receivedSignature);

            if (signatureMatch) {
                System.out.println("签名验证成功");
            } else {
                System.out.println("签名验证失败: Calculated=" + calculatedSignatureHex + ", Received=" + receivedSignature);
            }

            return signatureMatch;

        } catch (NoSuchAlgorithmException | InvalidKeyException e) {
            // 应该不会发生，因为HmacSHA256是标准算法
            e.printStackTrace();
            return false;
        }
    }


    public static void main(String[] args) {
        String username = "1222";
        String machineCode = "abaa58e97e7628aeb10b0437b205b6f57497a5ec832f2329d4a07d46ee942d88";
        String timestamp = "20250508103614";
        String receivedSignature = "fe336a58ff11bb341e4f388b44e3c370f6e362e152fbe7ad5e8ae68eb18f89c4";
        System.out.println(verifySignature(username, machineCode, timestamp, receivedSignature));

        System.out.println("================");
    }

}